public without sharing class AT_Opportunity_Trigger_Handler {

    private boolean m_isExecuting = false; 
    private integer BatchSize = 0;
         
    public AT_Opportunity_Trigger_Handler(boolean isExecuting, integer size)
    {
        m_isExecuting = isExecuting;
        BatchSize = size;
    }
    
	public void OnAfterUpdate(List<Opportunity> updatedOpps, Map<Id, Opportunity> newOppsMap, Map<Id, Opportunity> oldOppsMap)
	{
		List<Opportunity> lOpps2Process = new List<Opportunity>();
		Set<ID> inOppIDs = new Set<ID>();
		for(Opportunity item:updatedOpps)
		{
       		if(newOppsMap.get(item.id).StageName != oldOppsMap.get(item.id).StageName && newOppsMap.get(item.id).StageName=='Closed Won')
       		{
       			lOpps2Process.add(item);
       			inOppIDs.add(item.ID);
       		}
		}
		if(lOpps2Process.size()>0) AT_Opportunity_Trigger_Handler.createTransObjs(lOpps2Process, inOppIDs);
		
	}
	

	public static void createTransObjs(List<Opportunity> lOpps, Set<ID> inOppIDs)
	{
		map<ID,ID> mapTHExists = new map<ID,ID>();
		for(Transaction_Header__c item : [select ID,Opportunity__c from Transaction_Header__c where isFromOpportunity__c=true and Opportunity__c in :inOppIDs])
		{
			mapTHExists.put(item.Opportunity__c, item.Opportunity__c);
		}
		//if(listTH2Delete.size()>0) delete listTH2Delete;
		
		List<Transaction_Header__c> listTH2Insert = new List<Transaction_Header__c>();
		
		//System.debug('>>>>>>>>>>>>>>> lOpps: '+lOpps);
		for(Opportunity item:lOpps)
		{
			if(!mapTHExists.containsKey(item.ID))
			{
				Transaction_Header__c newTHItem = new Transaction_Header__c();
				newTHItem.Account__c = item.AccountId;
				newTHItem.Opportunity__c = item.ID;
				newTHItem.isFromOpportunity__c = true;
				newTHItem.FS_Date__c = item.CloseDate;
	
				newTHItem.FS_Total__c = item.Amount;
				newTHItem.Location_Name__c = item.Location_Name__c;
				//newTHItem.Location_ID__c = item.Location_ID__c;
				//newTHItem.Parent_ID__c = item.Parent_ID__c;
				//newTHItem.Office__c = item.Office__c;
				//newTHItem.Region__c = item.Region__c;
				//newTHItem.Class_ID__c = item.Class_ID__c;
				newTHItem.Class_Name__c = item.Class_Name__c;
				//newTHItem.Parent_Class_ID__c = item.Parent_Class_ID__c;
				listTH2Insert.add(newTHItem);
			}
		}
		insert listTH2Insert;
		
		
		
		Map<ID,ID> mapOppID2THID = new Map<ID,ID>();
		Set<ID> inNewOppIDs = new Set<ID>();
		for(Transaction_Header__c item:listTH2Insert)
		{
			mapOppID2THID.put(item.Opportunity__c, item.ID);
			inNewOppIDs.add(item.Opportunity__c);
		}
		
		//System.debug('>>>>>>>>>>>>>>> MAP: '+mapOppID2THID);

		List<Transaction_Detail__c> listTHDetInsert = new List<Transaction_Detail__c>();
		for(OpportunityLineItem item : [Select PricebookEntry.Product2Id,  PricebookEntry.Product2.GL_Group__c, Quantity, PricebookEntryId, OpportunityId,
				PricebookEntry.ProductCode, DEL_Name__c,Subtotal, DEL_ID__c, TotalPrice From OpportunityLineItem where OpportunityId in :inNewOppIDs])
		{
			Transaction_Detail__c newTHDetItem = new Transaction_Detail__c();
			newTHDetItem.Transaction_Header__c = mapOppID2THID.get(item.OpportunityId);
			//System.debug('>>>>>>>>>>>>>>> mapOppID2THID.get(item.OpportunityId): '+mapOppID2THID.get(item.OpportunityId));
			newTHDetItem.Product__c = item.PricebookEntry.Product2Id;
			newTHDetItem.FS_Product_Name__c = item.PricebookEntry.ProductCode;
			//newTHDetItem.Dept_ID__c = item.PricebookEntry.Product2.GL_Group__c;
			newTHDetItem.FS_Quantity__c = item.Quantity;
			newTHDetItem.FS_Subtotal__c = item.Subtotal;
			//newTHDetItem.DEL_ID__c = item.DEL_ID__c;
			//newTHDetItem.DEL_Name__c = item.DEL_Name__c;

			listTHDetInsert.add(newTHDetItem);
		}
		
		if(listTHDetInsert.size()>0) insert listTHDetInsert;
	}
}